/**
 * EduVerse Credentials - 凭证撤销机制实现
 * 
 * 本模块实现了两种凭证撤销机制:
 * 1. W3C Bitstring Status List v1.0
 * 2. Polygon ID原生撤销机制(Iden3 SMT)
 */

const { 
  CredentialStatusType 
} = require('@0xpolygonid/js-sdk');
const base64url = require('base64url');
const { v4: uuidv4 } = require('uuid');
const fs = require('fs').promises;
const path = require('path');

/**
 * W3C Bitstring Status List管理器
 */
class BitstringStatusListManager {
  /**
   * 创建W3C Bitstring Status List管理器
   * 
   * @param {Object} options - 配置选项
   */
  constructor(options = {}) {
    const {
      storageDir = './data/status-lists',
      baseUrl = 'http://localhost:3000/credentials/status',
      issuerDidUrl,
      issuerKeyPair
    } = options;
    
    this.storageDir = storageDir;
    this.baseUrl = baseUrl;
    this.issuerDidUrl = issuerDidUrl;
    this.issuerKeyPair = issuerKeyPair;
    this.indexMaps = new Map(); // 存储凭证ID到状态列表索引的映射
    this.initialized = false;
  }
  
  /**
   * 初始化管理器
   */
  async initialize() {
    console.log(`Initializing BitstringStatusListManager...`);
    
    try {
      // 确保存储目录存在
      await fs.mkdir(this.storageDir, { recursive: true });
      
      // 尝试加载现有的索引映射
      try {
        const indexMapData = await fs.readFile(
          path.join(this.storageDir, 'index-map.json'),
          'utf8'
        );
        this.indexMaps = new Map(JSON.parse(indexMapData));
        console.log(`Loaded ${this.indexMaps.size} status list indices`);
      } catch (err) {
        if (err.code !== 'ENOENT') {
          console.warn('Error loading index map:', err);
        }
        console.log('No existing index map found, creating new one');
      }
      
      this.initialized = true;
    } catch (error) {
      console.error('Error initializing BitstringStatusListManager:', error);
      throw error;
    }
  }
  
  /**
   * 创建新的状态列表凭证
   * 
   * @param {string} listId - 列表标识符
   * @param {number} listSize - 列表大小
   * @returns {Promise<Object>} 状态列表凭证和URL
   */
  async createStatusList(listId, listSize = 1024) {
    if (!this.initialized) await this.initialize();
    console.log(`Creating status list ${listId} with size ${listSize}...`);
    
    // 创建状态位字符串(初始全0，表示都未撤销)
    const bitstring = Buffer.alloc(Math.ceil(listSize / 8), 0);
    const encodedList = base64url.encode(bitstring);
    
    // 检查issuerDidUrl是否有效
    const issuer = this.issuerDidUrl || "did:example:placeholder";
    
    // 创建状态列表凭证
    const statusListCredential = {
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://www.w3.org/ns/credentials/examples/v2"
      ],
      "id": `${this.baseUrl}/${listId}`,
      "type": ["VerifiableCredential", "StatusList2021Credential"],
      "issuer": issuer,
      "issuanceDate": new Date().toISOString(),
      "credentialSubject": {
        "id": `${this.baseUrl}/${listId}#list`,
        "type": "StatusList2021",
        "statusPurpose": "revocation",
        "encodedList": encodedList
      }
    };
    
    // TODO: 添加Data Integrity证明 (在实际实现中需调用vc.js中的addDataIntegrityProof)
    // const signedStatusList = await addDataIntegrityProof(statusListCredential, this.issuerDidUrl, this.issuerKeyPair);
    const signedStatusList = statusListCredential; // 临时简化
    
    // 保存状态列表
    const filePath = path.join(this.storageDir, `${listId}.json`);
    await fs.writeFile(filePath, JSON.stringify(signedStatusList, null, 2));
    
    return {
      statusListCredential: signedStatusList,
      url: `${this.baseUrl}/${listId}`
    };
  }
  
  /**
   * 分配凭证状态索引
   * 
   * @param {string} credentialId - 凭证ID
   * @param {string} listId - 状态列表ID
   * @returns {Promise<Object>} 状态信息
   */
  async assignStatusIndex(credentialId, listId) {
    if (!this.initialized) await this.initialize();
    console.log(`Assigning status index for credential ${credentialId}...`);
    
    // 获取状态列表
    const filePath = path.join(this.storageDir, `${listId}.json`);
    let statusListCredential;
    
    try {
      const data = await fs.readFile(filePath, 'utf8');
      statusListCredential = JSON.parse(data);
    } catch (err) {
      if (err.code === 'ENOENT') {
        // 列表不存在，创建新列表
        const result = await this.createStatusList(listId);
        statusListCredential = result.statusListCredential;
      } else {
        throw err;
      }
    }
    
    // 分配索引
    // 简化实现: 这里仅分配递增索引，实际实现可能需要更复杂的位图管理
    let nextIndex = 0;
    const existingIndices = Array.from(this.indexMaps.values())
      .filter(entry => entry.listId === listId)
      .map(entry => entry.index);
    
    if (existingIndices.length > 0) {
      nextIndex = Math.max(...existingIndices) + 1;
    }
    
    // 保存索引映射
    this.indexMaps.set(credentialId, {
      listId,
      index: nextIndex,
      revoked: false
    });
    
    // 持久化索引映射
    await fs.writeFile(
      path.join(this.storageDir, 'index-map.json'),
      JSON.stringify(Array.from(this.indexMaps.entries()), null, 2)
    );
    
    return {
      listId,
      index: nextIndex,
      statusUrl: `${this.baseUrl}/${listId}`,
      statusId: `${this.baseUrl}/${listId}#${nextIndex}`
    };
  }
  
  /**
   * 撤销凭证
   * 
   * @param {string} credentialId - 要撤销的凭证ID
   * @returns {Promise<boolean>} 撤销是否成功
   */
  async revokeCredential(credentialId) {
    if (!this.initialized) await this.initialize();
    console.log(`Revoking credential ${credentialId}...`);
    
    // 查找凭证的状态索引
    const statusInfo = this.indexMaps.get(credentialId);
    if (!statusInfo) {
      console.warn(`Credential ${credentialId} not found in status index map`);
      return false;
    }
    
    const { listId, index, revoked } = statusInfo;
    
    // 如果已经撤销，不需要再次操作
    if (revoked) {
      console.log(`Credential ${credentialId} already revoked`);
      return true;
    }
    
    // 读取状态列表
    const filePath = path.join(this.storageDir, `${listId}.json`);
    let statusListCredential;
    
    try {
      const data = await fs.readFile(filePath, 'utf8');
      statusListCredential = JSON.parse(data);
    } catch (err) {
      console.error(`Error reading status list file:`, err);
      return false;
    }
    
    // 更新状态位字符串
    const bitstring = base64url.toBuffer(statusListCredential.credentialSubject.encodedList);
    bitstring[Math.floor(index / 8)] |= 1 << (7 - (index % 8));
    statusListCredential.credentialSubject.encodedList = base64url.encode(bitstring);
    
    // 更新状态列表凭证
    // TODO: 更新Data Integrity证明 (在实际实现中需调用vc.js中的updateDataIntegrityProof)
    // const updatedStatusList = await updateDataIntegrityProof(statusListCredential, this.issuerDidUrl, this.issuerKeyPair);
    const updatedStatusList = statusListCredential; // 临时简化
    
    // 保存更新后的状态列表
    await fs.writeFile(filePath, JSON.stringify(updatedStatusList, null, 2));
    
    // 更新索引映射
    this.indexMaps.set(credentialId, {
      listId,
      index,
      revoked: true
    });
    
    // 持久化索引映射
    await fs.writeFile(
      path.join(this.storageDir, 'index-map.json'),
      JSON.stringify(Array.from(this.indexMaps.entries()), null, 2)
    );
    
    return true;
  }
  
  /**
   * 获取状态列表凭证
   * 
   * @param {string} listId - 列表ID
   * @returns {Promise<Object>} 状态列表凭证
   */
  async getStatusList(listId) {
    if (!this.initialized) await this.initialize();
    
    const filePath = path.join(this.storageDir, `${listId}.json`);
    
    try {
      const data = await fs.readFile(filePath, 'utf8');
      return JSON.parse(data);
    } catch (err) {
      console.error(`Error reading status list ${listId}:`, err);
      throw err;
    }
  }
}

/**
 * Polygon ID Iden3 SMT撤销管理器
 */
class Iden3RevocationManager {
  /**
   * 创建Polygon ID Iden3 SMT撤销管理器
   * 
   * @param {Object} options - 配置选项
   */
  constructor(options = {}) {
    const {
      identityWallet,
      proofService,
      issuerDID
    } = options;
    
    this.identityWallet = identityWallet;
    this.proofService = proofService;
    this.issuerDID = issuerDID;
  }
  
  /**
   * 撤销凭证
   * 
   * @param {Object} credential - 要撤销的凭证
   * @param {Object} ethSigner - 以太坊签名者
   * @param {Object} dataStorage - 数据存储
   * @returns {Promise<Object>} 撤销结果
   */
  async revokeCredential(credential, ethSigner, dataStorage) {
    console.log(`Revoking credential ${credential.id} using Iden3 SMT...`);
    
    try {
      // 1. 撤销凭证(将撤销随机数添加到撤销树)
      await this.identityWallet.revokeCredential(credential);
      
      // 2. 发布状态到区块链
      console.log("Publishing updated state to blockchain...");
      
      // 由于我们使用的是模拟SDK，这里简化处理
      // 在实际实现中，需要获取当前状态和状态过渡参数
      // const txResult = await this.proofService.transitState(
      //   this.issuerDID,
      //   oldTreeState,
      //   false,
      //   dataStorage.states,
      //   ethSigner
      // );
      
      const txResult = { hash: "0x" + Math.random().toString(16).substring(2, 10) };
      
      console.log("Revocation state published on-chain. Transaction hash:", txResult.hash);
      return {
        success: true,
        transactionHash: txResult.hash
      };
    } catch (error) {
      console.error("Error revoking credential with Iden3 SMT:", error);
      return {
        success: false,
        error: error.message
      };
    }
  }
}

module.exports = {
  BitstringStatusListManager,
  Iden3RevocationManager
};